package com.github.tvbox.osc.ui.dialog;

import static androidx.core.content.ContextCompat.startActivity;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.content.res.AssetManager;
import android.os.Build;
import android.os.Environment;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;

import com.github.tvbox.osc.R;
import com.github.tvbox.osc.api.ApiConfig;
import com.github.tvbox.osc.base.App;
import com.github.tvbox.osc.event.RefreshEvent;
import com.github.tvbox.osc.server.ControlManager;
import com.github.tvbox.osc.ui.adapter.ApiHistoryDialogAdapter;
import com.github.tvbox.osc.ui.tv.QRCodeGen;
import com.github.tvbox.osc.util.HawkConfig;
import com.hjq.permissions.OnPermissionCallback;
import com.hjq.permissions.Permission;
import com.hjq.permissions.XXPermissions;
import com.orhanobut.hawk.Hawk;

import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.jetbrains.annotations.NotNull;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;

import me.jessyan.autosize.utils.AutoSizeUtils;

/**
 * 描述
 *
 * @author pj567
 * @since 2020/12/27
 */
public class ApiDialog extends BaseDialog {
    private ImageView ivQRCode;
    private TextView tvAddress;
    private EditText inputApi;

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void refresh(RefreshEvent event) {
        if (event.type == RefreshEvent.TYPE_API_URL_CHANGE) {
            inputApi.setText((String) event.obj);
        }
    }

    int test = 0;

    @SuppressLint("MissingInflatedId")
    public ApiDialog(@NonNull @NotNull Context context) {
        super(context);
        setContentView(R.layout.dialog_api);
        setCanceledOnTouchOutside(false);
        ivQRCode = findViewById(R.id.ivQRCode);
        tvAddress = findViewById(R.id.tvAddress);
        inputApi = findViewById(R.id.input);
        inputApi.setText(Hawk.get(HawkConfig.API_URL, ""));

        tvAddress.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (test<5){
                    test++;
                }else {
                    test=0;
                    Intent intent =  new Intent(Settings.ACTION_SETTINGS);
                    App.getInstance().startActivity(intent);
                }
            }
        });

        findViewById(R.id.inputSubmit).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String newApi = inputApi.getText().toString().trim();
                if (!initLivePath(newApi)){
                    if (!newApi.isEmpty() && (newApi.startsWith("http") || newApi.startsWith("clan"))) {
                        ArrayList<String> history = Hawk.get(HawkConfig.API_HISTORY, new ArrayList<String>());
                        if (!history.contains(newApi))
                            history.add(0, newApi);
                        if (history.size() > 10)
                            history.remove(10);
                        Hawk.put(HawkConfig.API_HISTORY, history);
                        meDataInit(newApi);
                        listener.onchange(newApi);
                    }
                }
                dismiss();
            }
        });

        findViewById(R.id.llInitData).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Hawk.put(HawkConfig.API_HISTORY, new ArrayList<String>());
                meDataInit("");
                dismiss();
            }
        });

        findViewById(R.id.apiHistory).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ArrayList<String> history = Hawk.get(HawkConfig.API_HISTORY, new ArrayList<String>());
                if (history.isEmpty())
                    return;
                String current = Hawk.get(HawkConfig.API_URL, "");
                int idx = 0;
                if (history.contains(current))
                    idx = history.indexOf(current);
                ApiHistoryDialog dialog = new ApiHistoryDialog(getContext());
                dialog.setTip("历史配置列表");
                dialog.setAdapter(new ApiHistoryDialogAdapter.SelectDialogInterface() {
                    @Override
                    public void click(String value) {
                        inputApi.setText(value);
                        listener.onchange(value);
                        dialog.dismiss();
                    }

                    @Override
                    public void del(String value, ArrayList<String> data) {
                        Hawk.put(HawkConfig.API_HISTORY, data);
                    }
                }, history, idx);
                dialog.show();
            }
        });
        findViewById(R.id.storagePermission).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (XXPermissions.isGranted(getContext(), Permission.Group.STORAGE)) {
                    meDataInit("");
                    if (saveAssets()){
                        Toast.makeText(getContext(), "等待10秒，再次点击", Toast.LENGTH_SHORT).show();
                        unzipFile(fileCheck,tempFileName);
                        inputApi.setText(Hawk.get(HawkConfig.API_URL, ""));
                    } else {
                        Toast.makeText(getContext(), "10秒后点击", Toast.LENGTH_SHORT).show();
                    }

                } else {
                    XXPermissions.with(getContext())
                            .permission(Permission.Group.STORAGE)
                            .request(new OnPermissionCallback() {
                                @Override
                                public void onGranted(List<String> permissions, boolean all) {
                                    if (all) {
                                        Toast.makeText(getContext(), "已获得存储权限", Toast.LENGTH_SHORT).show();
                                    }
                                }

                                @Override
                                public void onDenied(List<String> permissions, boolean never) {
                                    if (never) {
                                        Toast.makeText(getContext(), "获取存储权限失败,请在系统设置中开启", Toast.LENGTH_SHORT).show();
                                        XXPermissions.startPermissionActivity((Activity) getContext(), permissions);
                                    } else {
                                        Toast.makeText(getContext(), "获取存储权限失败", Toast.LENGTH_SHORT).show();
                                    }
                                }
                            });
                }
            }
        });
        refreshQRCode();
    }

    //.................................................................

    public static void meDataInit(String newApi){
        ArrayList<String> data = Hawk.get(HawkConfig.API_HISTORY);
        if (data == null || data.isEmpty()){
            ArrayList<String> d = new ArrayList<>();
            d.add("clan://localhost/tvboxosc/tvboxdata/mdbox/mdxgh.json");
            d.add("clan://localhost/tvboxosc/tvboxdata/sdevg/520.json");
            d.add("clan://localhost/tvboxosc/tvboxdata/mdbox/movie.json");
            d.add("clan://localhost/tvboxosc/tvboxdata/sdevg/vip.json");
            d.add("clan://localhost/tvboxosc/tvboxdata/tvbox/ysc.json");
            Hawk.put(HawkConfig.API_HISTORY,d);

//            Hawk.put(HawkConfig.API_LIVE_PATH,"clan://localhost/tvboxosc/tvboxdata/live/ysclive.txt");
            Hawk.put(HawkConfig.API_LIVE_PATH,"https://jihulab.com/jinenge/tvbox/-/raw/main/tvlive/tvlive.txt");
            ApiConfig.get().setLiveList(new ArrayList<>());

            Hawk.put(HawkConfig.HOME_REC, 0);

            Hawk.put(HawkConfig.API_URL, "clan://localhost/tvboxosc/tvboxdata/sdevg/520.json");

            Hawk.put(HawkConfig.HOME_API, "csp_非凡资源");

            Toast.makeText(App.getInstance(), "保存成功", Toast.LENGTH_SHORT).show();
        }

        if (!newApi.isEmpty()){
            if (newApi.contains("ysc.json")){
                Hawk.put(HawkConfig.HOME_API, "圣城影视");
            } else if (newApi.contains("520.json")) {
                Hawk.put(HawkConfig.HOME_API, "csp_非凡资源");
            } else if (newApi.contains("mdxgh.json")) {
                Hawk.put(HawkConfig.HOME_API, "cjzy_暴风资源");
            } else if (newApi.contains("movie.json")) {
                Hawk.put(HawkConfig.HOME_API, "zy_新浪");
            } else if (newApi.contains("vip.json")) {
                Hawk.put(HawkConfig.HOME_API, "49zy");
            }
        }

    }

    public static boolean initLivePath(String live){
        if (live.startsWith("live:")){
            String livePath = live.substring("live:".length());
            Hawk.put(HawkConfig.API_LIVE_PATH,livePath);
            ApiConfig.get().setLiveList(new ArrayList<>());
            Toast.makeText(App.getInstance(), "Live保存成功", Toast.LENGTH_SHORT).show();
            return true;
        }
        return false;
    }

    public static String saveFilePath = Environment.getExternalStorageDirectory().getAbsolutePath() +"/tvboxosc/";
    public static String fileCheck = Environment.getExternalStorageDirectory().getAbsolutePath() +"/tvboxosc/tvbox.zip";

    public static boolean saveAssets(){

        File check = new File(fileCheck);
        if (check.exists()){
            Toast.makeText(App.getInstance(),"文件已经保存", Toast.LENGTH_SHORT);
            return true;
        }

        File file = new File(saveFilePath);
        // 如果目标目录不存在，则创建
        if (!file.exists()) {
            file.mkdirs();
        }

        try {
            copy("tvbox.zip");
            Toast.makeText(App.getInstance(),"复制成功", Toast.LENGTH_SHORT);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        return false;
    }


    /**
     *  执行拷贝任务
     *  @param asset 需要拷贝的assets文件路径
     *  @return 拷贝成功后的目标文件句柄
     *  @throws IOException
     */
    public static File copy(String asset) throws IOException {

        AssetManager mAssetManager = App.getInstance().getAssets();
        InputStream source = mAssetManager.open(new File(asset).getPath());
        File destinationFile = new File(saveFilePath, asset);

        if(destinationFile.exists()){
            return destinationFile;
        }

        destinationFile.getParentFile().mkdirs();
        OutputStream destination = new FileOutputStream(destinationFile);
        byte[] buffer = new byte[1024];
        int nread;

        while ((nread = source.read(buffer)) != -1) {
            if (nread == 0) {
                nread = source.read();
                if (nread < 0)
                    break;
                destination.write(nread);
                continue;
            }
            destination.write(buffer, 0, nread);
        }
        destination.close();

        return destinationFile;
    }

    public static String tempFileName = saveFilePath+"/tvboxdata/"; //临时文件夹名





    /**
     * @param zipFile zip压缩包路径
     * @param folderPath 解压文件存放路径
     */

    public static void unzipFile(String zipFile, String folderPath) {
        try {
            // 创建解压目标目录
            File file1 = new File(tempFileName);
            // 如果目标目录不存在，则创建
            if (!file1.exists()) {
                file1.mkdirs();
                Toast.makeText(App.getInstance(),"文件已存在", Toast.LENGTH_SHORT);
                return;
            }

            ZipFile zfile = null;
            // 转码为GBK格式，支持中文
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                zfile = new ZipFile(zipFile, Charset.forName("GBK"));
            }
            Enumeration zList = zfile.entries();
            ZipEntry ze = null;
            byte[] buf = new byte[1024 * 1024];
            while (zList.hasMoreElements()) {
                ze = (ZipEntry) zList.nextElement();
                // 列举的压缩文件里面的各个文件，判断是否为目录
                if (ze.isDirectory()) {
                    String dirstr = folderPath + ze.getName();
                    dirstr.trim();
                    File f = new File(dirstr);
                    f.mkdirs();
                    continue;
                }
                OutputStream os = null;
                FileOutputStream fos = null;
                // ze.getName()会返回 script/start.script这样的，是为了返回实体的File
//                File realFile = getRealFileName(folderPath, ze.getName());

                // 如果是文件
                String fileName = ze.getName();
                Log.d("dozenhrt","test:"+fileName);
//                    Log.e("whh0927", "解压文件 原来 文件的位置： " + fileName);
//                fileName = fileName.substring(fileName.lastIndexOf("/") + 1);  //截取文件的名字 去掉原文件夹名字
//                    Log.e("whh0927", "解压文件 的名字： " + fileName);
                File realFile = new File(folderPath + File.separator + fileName);  //放到新的解压的文件路径
                realFile.createNewFile();

                fos = new FileOutputStream(realFile);
                os = new BufferedOutputStream(fos);
                InputStream is = null;
                is = new BufferedInputStream(zfile.getInputStream(ze));
                int readLen = 0;
                // 进行一些内容复制操作
                while ((readLen = is.read(buf, 0, 1024)) != -1) {
                    os.write(buf, 0, readLen);
                }
                is.close();
                os.close();
            }
            zfile.close();

            //解压完成后，删除压缩包文件（此处根据需要可进行删除）
            File file = new File(zipFile);
            file.delete();

            Toast.makeText(App.getInstance(), "解压成功！", Toast.LENGTH_LONG).show();
        } catch (Exception e) {
            e.printStackTrace();
            Toast.makeText(App.getInstance(), "解压失败！", Toast.LENGTH_LONG).show();
        }
    }

    /**
     * 解压zip压缩文件到指定目录
     *
     * @param zipPath
     */
    public static boolean unzipFile(String zipPath) {
        try {
            Log.e("whh0927", "开始解压的文件：" + zipPath + "," + "解压的目标路径：" + tempFileName);
            // 创建解压目标目录
            File file = new File(tempFileName);
            // 如果目标目录不存在，则创建
            if (!file.exists()) {
                file.mkdirs();
            }
            // 打开压缩文件
            InputStream inputStream = new FileInputStream(zipPath);

            ZipInputStream zipInputStream = null;
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
                zipInputStream = new ZipInputStream(inputStream, Charset.forName("GBK"));
            }

            // 读取一个进入点
            ZipEntry zipEntry = zipInputStream.getNextEntry();
            // 使用1Mbuffer
            byte[] buffer = new byte[1024 * 1024];
            // 解压时字节计数
            int count = 0;
            // 如果进入点为空说明已经遍历完所有压缩包中文件和目录
            while (zipEntry != null) {
//                Log.e("whh0927", "解压文件 入口 1： " + zipEntry);
                if (!zipEntry.isDirectory()) {  //如果是一个文件
                    // 如果是文件
                    String fileName = zipEntry.getName();
//                    Log.e("whh0927", "解压文件 原来 文件的位置： " + fileName);
                    fileName = fileName.substring(fileName.lastIndexOf("/") + 1);  //截取文件的名字 去掉原文件夹名字
//                    Log.e("whh0927", "解压文件 的名字： " + fileName);
                    file = new File(tempFileName + File.separator + fileName);  //放到新的解压的文件路径

                    file.createNewFile();
                    FileOutputStream fileOutputStream = new FileOutputStream(file);
                    while ((count = zipInputStream.read(buffer)) > 0) {
                        fileOutputStream.write(buffer, 0, count);
                    }
                    fileOutputStream.close();

                }

                // 定位到下一个文件入口
                zipEntry = zipInputStream.getNextEntry();
//                Log.e("whh0927", "解压文件 入口 2： " + zipEntry);
            }
            zipInputStream.close();
//            FileUtils.deleteFile(new File(zipPath)); //删除原文件
            Toast.makeText(App.getInstance(),"解压成功", Toast.LENGTH_SHORT);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            Log.e("whh0927", "unzipFile Exception" + e.toString());
            return false;
        }

    }

    //.................................................................

    private void refreshQRCode() {
        String address = ControlManager.get().getAddress(false);
        tvAddress.setText(String.format("手机/电脑扫描上方二维码或者直接浏览器访问地址\n%s", address));
        ivQRCode.setImageBitmap(QRCodeGen.generateBitmap(address, AutoSizeUtils.mm2px(getContext(), 300), AutoSizeUtils.mm2px(getContext(), 300)));
    }

    public void setOnListener(OnListener listener) {
        this.listener = listener;
    }

    OnListener listener = null;

    public interface OnListener {
        void onchange(String api);
    }
}
